package com.yonyou.iuap.pub;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

public class DateUtil extends DateUtils
{
  private static GregorianCalendar gc = new GregorianCalendar(Locale.CHINA);

  private static String[] parsePatterns = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", 
    "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm" };

  static
  {
    gc.setLenient(true);
    gc.setFirstDayOfWeek(2);
  }

  public static String getDate()
  {
    return getDate("yyyy-MM-dd");
  }

  public static String getDate(String pattern)
  {
    return DateFormatUtils.format(new Date(), pattern);
  }

  public static String formatDate(Date date, Object[] pattern)
  {
    String formatDate = null;
    if ((pattern != null) && (pattern.length > 0))
      formatDate = DateFormatUtils.format(date, pattern[0].toString());
    else {
      formatDate = DateFormatUtils.format(date, "yyyy-MM-dd");
    }
    return formatDate;
  }

  public static String formatDateTime(Date date)
  {
    return formatDate(date, new Object[] { "yyyy-MM-dd HH:mm:ss" });
  }

  public static String getTime()
  {
    return formatDate(new Date(), new Object[] { "HH:mm:ss" });
  }

  public static String getDateTime()
  {
    return formatDate(new Date(), new Object[] { "yyyy-MM-dd HH:mm:ss" });
  }

  public static String getYear()
  {
    return formatDate(new Date(), new Object[] { "yyyy" });
  }
  public static String getYear(String date){
	  return formatDate(convertStringToDate(date), new Object[] { "yyyy" });
  }
  public static String getMonth()
  {
    return formatDate(new Date(), new Object[] { "MM" });
  }
  public static String getMonth(String date){
	  return formatDate(convertStringToDate(date), new Object[] { "MM" });
  }
  public static String getDay()
  {
    return formatDate(new Date(), new Object[] { "dd" });
  }
  public static String getDay(String date){
	  return formatDate(convertStringToDate(date), new Object[] { "dd" });
  }
  public static String getWeek()
  {
    return formatDate(new Date(), new Object[] { "E" });
  }

  public static Date parseDate(Object str)
  {
    if (str == null)
      return null;
    try
    {
      return parseDate(str.toString(), parsePatterns); } catch (ParseException e) {
    }
    return null;
  }

  public static long pastDays(Date date)
  {
    long t = new Date().getTime() - date.getTime();
    return t / 86400000L;
  }

  public static Date getDateStart(Date date)
  {
    if (date == null) {
      return null;
    }
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    try {
      date = sdf.parse(formatDate(date, new Object[] { "yyyy-MM-dd" }) + " 00:00:00");
    } catch (ParseException e) {
      e.printStackTrace();
    }
    return date;
  }

  public static Date getDateEnd(Date date) {
    if (date == null) {
      return null;
    }
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    try {
      date = sdf.parse(formatDate(date, new Object[] { "yyyy-MM-dd" }) + " 23:59:59");
    } catch (ParseException e) {
      e.printStackTrace();
    }
    return date;
  }

  public static Date getCurrentDate()
  {
    Date date = new Date(System.currentTimeMillis());
    return date;
  }

  public static int getCurrentTime(TimeFormatType timeFormatType)
  {
    return getTime(getCurrentDate(), timeFormatType);
  }

  public static int getTime(Date date, TimeFormatType timeFormatType)
  {
    try
    {
      Calendar c = Calendar.getInstance();
      c.setTime(date);
      int type = timeFormatType.getValue();
      int i = c.get(type);
      return type == 2 ? i + 1 : i;
    } catch (Exception e) {
      throw new RuntimeException("获取失败", e);
    }
  }

  public static long getMillis(Date date)
  {
    Calendar c = Calendar.getInstance();
    c.setTime(date);
    return c.getTimeInMillis();
  }

  public static int operationDate(Date date, Date diffDate, DateOperationType dateOperationType)
  {
    long add = getMillis(date) + getMillis(diffDate);
    long diff = getMillis(date) - getMillis(diffDate);
    return (int)((dateOperationType.getValue() ? add : diff) / 86400000L);
  }

  public static Date operationDateOfMonth(Date date, int month, DateOperationType dateOperationType)
  {
    Calendar c = Calendar.getInstance();
    c.setTime(date);
    c.add(2, dateOperationType.getValue() ? month : month - month * 2);
    return c.getTime();
  }

  public static Date operationDateOfDay(Date date, int day, DateOperationType dateOperationType)
  {
    Calendar c = Calendar.getInstance();
    c.setTime(date);
    long millis = c.getTimeInMillis();
    long millisOfday = day * 24 * 3600 * 1000;
    long sumMillis = dateOperationType.getValue() ? millis + millisOfday : millis - millisOfday;
    c.setTimeInMillis(sumMillis);
    return c.getTime();
  }

  private static Object OpearationDate(Object object, String formatStr)
  {
    if ((object == null) || (formatStr == null) || ("".equals(formatStr))) {
      throw new RuntimeException("参数不能为空");
    }
    SimpleDateFormat format = new SimpleDateFormat(formatStr);
    try {
      if ((object instanceof Date)) {
        return format.format(object);
      }
      return format.parse(object.toString());
    } catch (Exception e) {
      throw new RuntimeException("操作失败", e);
    }
  }

  public static Date getLastWorkDay(Date curDate, int n)
  {
    Date beginDate = curDate;
    Date endDate = curDate;
    for (int i = 0; i < n; i++) {
      endDate = new Date(endDate.getTime() - 86400000L);
      int day_of_week = getDayOfWeek(endDate).intValue();
      if (day_of_week == 1) {
        beginDate = endDate;
        endDate = new Date(endDate.getTime() - 172800000L);
      } else if (day_of_week == 7) {
        beginDate = endDate;
        endDate = new Date(endDate.getTime() - 86400000L);
      }
    }
    return endDate;
  }

  public static Integer getDayOfWeek(Date date) {
    Calendar cal = new GregorianCalendar();
    cal.setTime(date);
    return Integer.valueOf(cal.get(7));
  }

  private static void initCalendar(Date date)
  {
    if (date == null) {
      throw new IllegalArgumentException("argument date must be not null");
    }
    gc.clear();
    gc.setTime(date);
  }

  public static Date getAfterDate(Date date, int days)
  {
    initCalendar(date);
    gc.set(6, gc.get(6) + days);
    return gc.getTime();
  }

  public static boolean before(String first, String second) {
    SimpleDateFormat dfs = new SimpleDateFormat("yyyy-MM-dd");

    Date a = null; Date b = null;
    try {
      a = dfs.parse(first);
      b = dfs.parse(second);
    }
    catch (ParseException e) {
      e.printStackTrace();
    }

    return a.before(b);
  }

  public static boolean before(String first, String second, String pattern)
  {
    SimpleDateFormat dfs = new SimpleDateFormat(pattern);

    Date a = null; Date b = null;
    try {
      a = dfs.parse(first);
      b = dfs.parse(second);
    }
    catch (ParseException e) {
      e.printStackTrace();
    }

    return a.before(b);
  }

  public static final String getDateStr(Date aDate)
  {
    SimpleDateFormat df = null;
    String returnValue = "";

    if (aDate != null) {
      df = new SimpleDateFormat(parsePatterns[0]);
      returnValue = df.format(aDate);
    }
    return returnValue;
  }

  public static final String getTimeStr(Date aDate)
  {
    SimpleDateFormat df = null;
    String returnValue = "";

    if (aDate != null) {
      df = new SimpleDateFormat(parsePatterns[1]);
      returnValue = df.format(aDate);
    }

    return returnValue;
  }

  public static Date convertStringToDate(String strDate)
  {
    Date aDate = null;
    try
    {
      String pattern = "\\d{4}[-|/]\\d{2}[-|/]\\d{2}[ ]\\d{2}[:]\\d{2}[:]\\d{2}";
      if (strDate.matches(pattern)) {
        if (strDate.contains("/"))
          aDate = convertStringToDate("yyyy/MM/dd HH:mm:ss", strDate);
        else {
          aDate = convertStringToDate(parsePatterns[1], strDate);
        }
      }
      else if (strDate.contains("/"))
        aDate = convertStringToDate("yyyy/MM/dd", strDate);
      else {
        aDate = convertStringToDate(parsePatterns[0], strDate);
      }

    }
    catch (ParseException pe)
    {
      pe.printStackTrace();
    }

    return aDate;
  }

  public static final Date convertStringToDate(String aMask, String strDate)
    throws ParseException
  {
    SimpleDateFormat df = null;
    Date date = null;
    df = new SimpleDateFormat(aMask);
    try
    {
      date = df.parse(strDate);
    }
    catch (ParseException pe) {
      throw new ParseException(pe.getMessage(), pe.getErrorOffset());
    }

    return date;
  }

  public static final String getTimeStr(String format, Date aDate)
  {
    SimpleDateFormat df = null;
    String returnValue = "";

    if (aDate != null) {
      df = new SimpleDateFormat(format);
      returnValue = df.format(aDate);
    }

    return returnValue;
  }

  public static enum DateFormatType
  {
    DATE_FORMAT_STR(
      "yyyy-MM-dd HH:mm:ss"), 
    SIMPLE_DATE_TIME_FORMAT_STR(
      "yyyyMMddHHmmss"), 

    SIMPLE_DATE_FORMAT_STR(
      "yyyy-MM-dd"), 

    SIMPLE_DATE_FORMAT_VIRGULE_STR(
      "yyyy/MM/dd"), 

    HOUR_MINUTE_SECOND(
      "HH:mm:ss"), 

    HOUR_MINUTE(
      "HH:mm");

    private final String value;

    private DateFormatType(String formatStr) {
      this.value = formatStr;
    }

    public String getValue() {
      return this.value;
    }
  }

  public static enum DateOperationType
  {
    ADD(
      true), 

    DIFF(
      false);

    private final boolean value;

    private DateOperationType(boolean operation) {
      this.value = operation;
    }

    public boolean getValue() {
      return this.value;
    }
  }

  public static enum TimeFormatType
  {
    YEAR(1), MONTH(2), DAY(5), HOUR(11), MINUTE(12), SECOND(13);

    private final int value;

    private TimeFormatType(int formatStr) { this.value = formatStr; }

    public int getValue()
    {
      return this.value;
    }
  }
}